﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Text;

namespace Xcap
{
    namespace Xml
    {
        /// <summary>
        /// Object representing a contact
        /// </summary>
        public class Contact
        {
            string uri;
            string displayName;
            
            /// <summary>
            /// Get current uri value of the Contact
            /// </summary>
            public string Uri { get { return uri; } }

            /// <summary>
            /// Get Current display name of the Contact
            /// </summary>
            public string DisplayName { get { return displayName; } }


            public Contact(string _uri, string _displayName) 
            {
                uri = _uri;
                displayName = _displayName;
            }

            public Contact(string _uri)
            {
                uri = _uri;
            }
        }

        /// <summary>
        /// Class adds resource list object
        /// </summary>
        public class XcapXmlResourceLists : Xml
        {
            //public List<contact> contacts           

            public XcapXmlResourceLists() : base(xcapDocument.resourceLists)
            {
                //vytvorime objekt na resource-list
                AddResourceLists();
            }

            public void NewContactList(string name, string displayName, List<Contact> _contacts)
            {
                //novy list     
                XElement list = AddList(name, displayName);

                foreach (Contact item in _contacts)
                {
                    AddEntry(list, item.Uri, item.DisplayName);
                }

                resourceLists.Add(list);

                #region use
                //AddResourceLists();
                //XElement list = AddList("priatelia", "Moji priatelia");

                //AddEntry(list, "sip:rv_user5@ngnlab.eu", "Verbatim Moucha");
                //AddEntry(list, "sip:rv_user6@ngnlab.eu", "Peter Stajger");

                //XElement list2 = AddList("nepriatelia", "Moji nepriatelia");
                //AddEntry(list2, "sip:rv_user7@ngnlab.eu", "Radoslav Vargic");
                //AddEntry(list2, "sip:rv_user8@ngnlab.eu", "Ing. Eva Samuhelova");

                //resourceLists.Add(list);
                //resourceLists.Add(list2);

                //xDocument.Add(resourceLists);
                //string ret = xDocument.Declaration + "\n\r" + xDocument.Root.ToString();
                //return ret;
                #endregion
            }

            public string NewContact(Contact contact)
            {
                XElement entry = new XElement(seEntry.nameSpace + seEntry.nodeName);
                XAttribute uri = new XAttribute("uri", contact.Uri);
                XElement displayName = new XElement(seDisplayName.nameSpace + seDisplayName.nodeName);
                displayName.Add(contact.DisplayName);
                entry.Add(uri);
                entry.Add(displayName);
                return entry.ToString();
            }

            public string GetResourceLists()
            { 
                xDocument.Add(resourceLists);
                string ret = xDocument.Declaration + "\n\r" + xDocument.Root.ToString();
                return ret;
            }
        }

        /// <summary>
        /// Class using xcap.xml class woring with pidf, rpid, cipid objects
        /// This clas support only one tuple, person and device element
        /// </summary>
        public class XcapXmlPresence : Xml
        {
            private xcapElement xcapTuple;
            private xcapElement xcapPerson;
            private xcapElement xcapDevice;

            /// <summary>
            /// Method is being applied on the Tuple. Usually used to specify 
            /// particular RPID or CIPID extention.
            /// </summary>
            public xcapElement Tuple { get { return xcapTuple; } }
            /// <summary>
            /// Method is being applied on the Person. Usually used to specify 
            /// particular RPID or CIPID extention.
            /// </summary>
            public xcapElement Person { get { return xcapPerson; } }
            /// <summary>
            /// Method is being applied on the Device. Usually used to specify 
            /// particular RPID or CIPID extention.
            /// </summary>
            public xcapElement Device { get { return xcapDevice; } }

            public XcapXmlPresence(string userUri) : base(xcapDocument.pidf)
            {
                //nastavime usera
                User = userUri;
                AddPresence();
            }

            /// <summary>
            /// Adds a basic tuple element into a presence element
            /// </summary>
            /// <param name="id">id attribute of tuple</param>
            /// <param name="status">basic status enum</param>
            /// <param name="contact">contact information</param>
            /// <param name="note">note</param>
            public void NewTuple(string id, xcapBasicStatus status, string contact, string priority, string note)
            {
                XElement tuple = AddTuple(id, status, contact, priority, note);
                //pri timestamp nie je vyrieseny format
                //AddTimeStamp(tuple, PI, "9809342093");

                xcapTuple.xelement = tuple;
                xcapTuple.allowed = xcapRpidSupportingElements.tuple;
            }

            public void NewPerson(string id, string note)
            {
                XElement person = AddPerson(id, note);
                xcapPerson.xelement = person;
                xcapPerson.nameSpace = DM;
                xcapPerson.allowed = xcapRpidSupportingElements.person;
            }

            public void NewDevice(string id, string idDevice, xcapBasicStatus status, string note)
            {
                XElement device = AddDevice(id, idDevice, status, note);
                xcapDevice.xelement = device;
                xcapDevice.nameSpace = DM;
                xcapDevice.allowed = xcapRpidSupportingElements.device;
            }

            public string GetPresence()
            {
                presence.Add(xcapTuple.xelement);
                presence.Add(xcapPerson.xelement);
                presence.Add(xcapDevice.xelement);
                xDocument.Add(presence);
                return xDocument.Declaration + "\n\r" + xDocument.Root.ToString();
            }

            /// <summary>
            /// Allow to add extra note into XElement specified by xcapElement struct
            /// </summary>
            /// <param name="addTo">Add note to this element</param>
            /// <param name="text">Text of note</param>
            public void AddNote(xcapElement addTo, string text)
            {
                XElement note;
                note = new XElement(addTo.nameSpace + seNote.nodeName);
                note.Add(text);
                addTo.xelement.Add(note);
            }

        }

        public class XcapXmlPresrules : Xml
        {
            /// <summary>
            /// List of rules in one ruleset element
            /// </summary>
            List<XElement> rules = new List<XElement>();

            public XcapXmlPresrules() : base(xcapDocument.presRules)
            {
                //vytvorime objekt na resource-list
                AddPresRules();
            }

            public XElement NewIdentity(Contact contact)
            {
                XAttribute id = new XAttribute("id", contact.Uri);
                XElement one = new XElement(seOne.nameSpace + seOne.nodeName);
                one.Add(id);
                return one;
            }

            public void NewRule(string id, List<Contact> contacts, xcapPresRulesActions action, bool supportPidf)
            {
                XElement rule = AddRule(id);
                XElement conditions = new XElement(seConditions.nameSpace + seConditions.nodeName);
                XElement actions = new XElement(seActions.nameSpace + seActions.nodeName);
                XElement subHandling = new XElement(seSubHandling.nameSpace + seSubHandling.nodeName);
                XElement identity = new XElement(seIdentity.nameSpace + seIdentity.nodeName);

                //XElement one = new XElement(seOne.nameSpace + seOne.nodeName);

                foreach (Contact item in contacts)
                {
                    AddOne(identity, item.Uri);
                }

                //conditions
                conditions.Add(identity);
                rule.Add(conditions);

                //subhandling
                switch (action)
                { 
                    case xcapPresRulesActions.allow:
                        subHandling.Add(action);
                        AddTransformations(rule, supportPidf);
                        break;
                    case xcapPresRulesActions.block:
                    case xcapPresRulesActions.confirm:
                        subHandling.Add(action);
                        break;
                    case xcapPresRulesActions.polite_block:
                        subHandling.Add("polite-block");
                        break;
                }

                actions.Add(subHandling);
                rule.Add(actions);

                rules.Add(rule);
            }

            public string GetPresRules()
            {
                foreach (XElement item in rules)
                {
                    presRules.Add(item);
                }

                xDocument.Add(presRules);
                return xDocument.Declaration + "\n\r" + xDocument.Root.ToString();
            }
        }
    }
}
